﻿/*
 * XtcpConnection.h
 *
 */
#ifndef __GDK_XTCPCONNECTION_H__
#define __GDK_XTCPCONNECTION_H__

#include <gdk/net/Socket.h>
#include <gdk/net/NetTcpConnection.h>
#include <gdk/core/Task.h>
#include <gdk/core/MemoryStream.h>
#include <gdk/core/MessageDispenser.h>
#include <list>


namespace gdk
{

	class GDK_NET_EXPORT XtcpConnection : public Task
	{
		DECLARE_CLASS_HANDLE(XtcpConnection)
		DECLARE_CLASS_INSTANCE(XtcpConnection)

		friend class XtcpServer;

		typedef std::list<Message::Handle>	XtcpMsgList;

	public:
		enum ConnectionState
		{
			INVALID,		//无效
			CONNECTING,		//连接中
			CONNECTED,		//连接
			CONNECTTIMEOUT,	//连接超时
			CLOSED,			//连接关闭
			ABORT,			//连接中断
		};

	private:
		NetTcpConnectionPtr		_conn;
		ConnectionState			_connectionState;
		MessageDispenser<void>	_messageDispenser;

		String					_ip;
		uint16_t				_port;

		bool					_isClient;
		uint32_t				_timeout;
		bool					_isBlocking;
		uint32_t				_activeTime;
		bool					_waitEcho;

		Uuid					_myId;
		Uuid					_targetId;

		MemoryStream::Handle	_recvMemBuffer;
		MemoryStream::Handle	_sendMemBuffer;

		uint8_t					_ack;
		uint8_t					_sequence;
		XtcpMsgList				_msgBuffer;

		uint8_t					_ackLast; //最后一次发送ack
		uint32_t				_timeLastSend; //最后一次发送数据的时间
		int						_tryTimeIfAbort; //尝试连接时间,如果出现中断

		uint32_t				_beginConnectTime; //开始建立连接时间(通过它来检查会话握手超时)

	protected:
		XtcpConnection(void);
		~XtcpConnection(void);

	public:
		virtual bool start(System *system);
		virtual void stop(void);
		virtual void onTick(uint32_t timeSinceLastTick);
		//------------------------------------------------------------------

	public:
		virtual bool attach(NetTcpConnection* conn);
		virtual NetTcpConnectionPtr detach(void);
		virtual bool connect(const Char *ip, unsigned short port);
		virtual void close(void);
		virtual ssize_t available(void) const;
		virtual ssize_t receive(void *buf, ssize_t size);
		virtual ssize_t send(const void *data, ssize_t size);
		//------------------------------------------------------------------

	public:
		void setConnectionState(ConnectionState connectionState);
		__INLINE__ bool isInvalid(void) const { return _conn.isNull(); }
		__INLINE__ bool isBlocking(void) const { return _isBlocking; }
		__INLINE__ ConnectionState getConnectionState(void) const { return _connectionState; }
		__INLINE__ MessageDispenser<void>& getMessageDispenser(void) { return _messageDispenser; }
		//------------------------------------------------------------------

		bool    getPeerName(__sockaddr_in &addr) const;
		void    getPeerName(String &ip, uint16_t &port) const;
		String  getPeerName(void) const;
		//------------------------------------------------------------------


	private:
		void hello(void);
		void imHere(void);
		void bye(void);
		void ackdata(uint8_t ack);
		void sendXtcpData(class XtcpData *xtcpData);
		void resendXtcpData(void);
	private:
		void onTcpConnectOk(const Evt_NetTcpConnectOk *evt);
		void onTcpConnectFail(const Evt_NetTcpConnectFail *evt);
		void onTcpClosed(const Evt_NetTcpClosed *evt);
		void onTcpError(const Evt_NetTcpError *evt);
		void onTcpAbort(const Evt_NetTcpAbort *evt);
		void onTcpReceive(const Evt_NetTcpReceive *evt);
		//------------------------------------------------------------------
		void onXtcpHello(class XtcpHello *msg);
		void onXtcpImHere(class XtcpImHere *msg);
		void onXtcpBye(class XtcpBye *msg);
		void onXtcpAbort(class XtcpAbort *msg);
		void onXtcpData(class XtcpData *msg);
		//------------------------------------------------------------------
	};
	typedef XtcpConnection::Handle	XtcpConnectionPtr;


} //namespace gdk


#endif //__GDK_XTCPCONNECTION_H__
